package com.ruoyi.web.Interceptord;

import com.ruoyi.common.exception.user.AntiReplayException;
import com.ruoyi.common.exception.user.IntegrityErrorException;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
public class FcfIntercepter implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${OriginUrl.params}")
    private String urlParams;

    public static String encrypt(String paramStr){
        // 将返回的hash值转换成16进制字符串
        String resultHexString = "";
        try {
            // 将字符串转换成byte数组
            byte[] srcData = paramStr.getBytes("UTF-8");
            // 调用hash()
            byte[] resultHash = hash(srcData);
            // 将返回的hash值转换成16进制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            log.info(e.toString());
        }
        return resultHexString;
    }

    public static byte[] hash(byte[] srcData){
        SM3Digest digest = new SM3Digest();
        digest.update(srcData,0,srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash,0);
        return hash;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//"/login".equals(request.getHeader("url"))  ||  "/getInfo".equals(request.getHeader("url")) ||

        //放行

//        log.info("挡前的url地址   {}   {}" ,request.getRequestURI(),request.getRequestURI());
//        if( request.getRequestURI().contains("getPublicKey") || request.getRequestURI().contains("insertPublicKey") || request.getRequestURI().contains("captchaImage")){//|| request.getHeader("url") == null
//            log.info("登录放行~~~~~");
//            return true;
//        }
//        log.info("当前的url是==== 》   {}",request.getRequestURI());
//        //<6>服务端收到请求后，读取参数值timestamp、nonce_client、sign_client,并对这三个参数做非空判断
//        String time = request.getHeader("time");
//        String nonce_client = request.getHeader("nonceclient");
//        String hash = request.getHeader("hash");
//
//        if("".equals(time)  || "".equals(nonce_client) || "".equals(hash) || time ==null || nonce_client==null || hash == null){
//            //错误  throw new IntegrityErrorException();
//            log.info("三个值，总有一个是null的");
//            throw new AntiReplayException();
//        }
//        //
//        String uid = (String) redisTemplate.opsForValue().get("uid");
//        log.info("加密之前的hash {}",hash);
//
//        //用现在的时间对比 发送过来的时间
//        long nowTime = System.currentTimeMillis();
//        log.info("打印当前后端的时间 {}",nowTime);
//        log.info("打印当前前端发送过来的时间 {}",time);
//        log.info("打印时间的差值是多少 {}",String.valueOf(nowTime - Long.parseLong(time)));
//        //<7>验证timestamp参数，服务端当前时间timestamp_now-timestamp是否大于60s或<-5s（默认一次HTTP请求从发出到到达服务器的时间是不会超过60s的，且不会小于0，考虑到计算机精度和多网关业务场景，故判断条件为>60s或<-5s）。若大于60s或<-5s
//        long b = nowTime - Long.parseLong(time);
//
//
//
//        if( b > 60000 || b < -5000 ){
//            log.info("当前的值   在 b > 60000 || b < -5 范围之间 ==>  {}  ", b );
//            throw new AntiReplayException();
//        }
//        log.info("到这里 所有的时间差值都是正常的  ==》 {}",b);
//        // <8>  验证nonce_client参数，nonce_client在服务端缓存中是否存在，如果存在则请求无效，视为重放攻击
//        if (redisTemplate.hasKey(nonce_client)){
//            log.info("如果数据库已经存在这个nonce_client了  应该报错");
//            throw new AntiReplayException();
//        } else {
//            //没有使用，存储起来，设置过期时间为当前访问时间+判断请求过期的时间
//            //这样就不用定时任务去清除之前的nonce，利用redis自动清除
//            log.info("没有这个 nonce_client");
//            redisTemplate.opsForValue().set(nonce_client, nonce_client);
//        }
//        //<9>验证sign_client参数，服务端根据请求的会话标识读取该用户的uid参数，
//        String result = encrypt(time+","+nonce_client+","+uid);
//        log.info("加密之前的三格值 {} {} {}",time,nonce_client,uid);
//        log.info("加密之后的hash {}",result);
//        log.info("加密之后的hash {}",result.equals(hash));
//        if(!result.equals(hash)){
//            throw new AntiReplayException();
//        }
        //最后验证验签

        return true;
    }
}
